﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.SessionState;
using System.Xml.Linq;

using Microsoft.SqlServer.Types;
using System.Data.Sql;
using System.Data.SqlClient;

using MapViewer;

namespace DrawMap
{
    /// <summary>
    /// Summary description for MapViewer_Service
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    [System.Web.Script.Services.ScriptService]
    public class MapViewer_Service : System.Web.Services.WebService
    {
        // Whether or not to show "clickable" map - e.g. should we generate
        // the html <area> control
        [Bindable(true)]
        [Category("Setup")]
        [DefaultValue("")]
        public bool GenerateClickMap
        {
            get { return Session.Get_Boolean("GenerateClickMap"); }
            set { Session.Set_Boolean("GenerateClickMap", value); }
        }

        // URL to go to when a region on the map is clicked
        [Bindable(true)]
        [Category("Setup")]
        [DefaultValue("")]
        [Localizable(true)]
        public string MapUrl
        {
            get { return Session.Get_String("MapUrl"); }
            set { Session.Set_String("MapUrl", value); }
        }

        // value to pass as 'key', added to the MapUrl link
        [Bindable(true)]
        [Category("Setup")]
        [DefaultValue("")]
        [Localizable(true)]
        public String MapKey
        {
            get { return Session.Get_String("MapKey"); }
            set { Session.Set_String("MapKey", value); }
        }

        // value to pass as 'field', added to the MapUrl link
        [Bindable(true)]
        [Category("Setup")]
        [DefaultValue("")]
        [Localizable(true)]
        public String MapField
        {
            get { return Session.Get_String("MapField"); }
            set { Session.Set_String("MapField", value); }
        }

        // unit displayed in scale text in corner of control
        [Bindable(true)]
        [Category("Setup")]
        [DefaultValue("")]
        [Localizable(true)]
        public String MapUnits
        {
            get { return Session.Get_String("MapUnits"); }
            set { Session.Set_String("MapUnits", value); }
        }
        //---------------------------------------------------------------------
        // save height and width of the image to draw
        //---------------------------------------------------------------------
        private float width
        {
            get { return Session.Get_Float("width"); }
            set { Session.Set_Float("width", value); }
        }

        private float height
        {
            get { return Session.Get_Float("height"); }
            set { Session.Set_Float("height", value); }
        }

        //---------------------------------------------------------------------
        //---------------------------------------------------------------------
        // Internal Variables
        //---------------------------------------------------------------------
        //---------------------------------------------------------------------

        // drawing object
        internal Drawing drawing = new Drawing();

        // collection of all the layers that we're going to draw
        internal LayerManager layermanager = new LayerManager();

        // internal diagnostic - count the time to do all our work
        private DateTime start;
        private DateTime stop;

        //---------------------------------------------------------------------
        // Data structure to return to the client
        //---------------------------------------------------------------------
        public class MapData
        {
            public String mapurl;
            public String top;
            public String left;
            public String bottom;
            public String right;
            public String scaletext;
            public String pathcounter;
            public String geocounter;
            public String duration;
            public String areahtml;
        }

        //---------------------------------------------------------------------
        //---------------------------------------------------------------------
        // Methods
        //---------------------------------------------------------------------
        //---------------------------------------------------------------------

        private void Initialize()
        {
            // check for things that must be defined for this to work
            if (GenerateClickMap)
            {
                if (String.IsNullOrEmpty(MapUrl))
                    throw new Exception("MapUrl must be defined for click-map processing");
                if (String.IsNullOrEmpty(MapKey))
                    MapKey = "key";
                if (String.IsNullOrEmpty(MapField))
                    MapField = "field";
            }

            // recover saved layer manager 
            if (null != Session["layermanager"])
            {
                layermanager = (LayerManager)Session["layermanager"];
            }

            if (0 == layermanager.Count)
                throw new Exception("At least one layer must be defined");

            // send values to drawing object
            drawing.GenerateClickMap = GenerateClickMap;
            drawing.MapField = MapField;
            drawing.MapKey = MapKey;
            drawing.MapUrl = MapUrl;
            drawing.width = width;
            drawing.height = height;
        }


        // Accept a set of coordinates, draw the map and return the map image
        // source name, new coordinates, and area html. Note that the "ScriptService"
        // attribute means that the return data is automatically reformatted as JSON
        [WebMethod(EnableSession=true)]
        public MapData GetMapByCoords(String top, String left, String bottom, String right)
        {
            start = DateTime.Now;

            // make sure we're set up to go
            Initialize();
            

            // create polygon text - manually create our new envelope
            StringBuilder poly = new StringBuilder();
            poly.Append("POLYGON((");
            poly.Append(left.ToString()).Append(" ").Append(top.ToString()).Append(", ");
            poly.Append(right.ToString()).Append(" ").Append(top.ToString()).Append(", ");
            poly.Append(right.ToString()).Append(" ").Append(bottom.ToString()).Append(", ");
            poly.Append(left.ToString()).Append(" ").Append(bottom.ToString()).Append(", ");
            poly.Append(left.ToString()).Append(" ").Append(top.ToString()).Append(" ");
            poly.Append("))");

            // set the envelope into the layer manager
            layermanager.EnvelopeFromText(poly.ToString());

            // get data and draw based on our new region
            drawing.DrawAllLayers(layermanager);

            // save drawing results to HTML return object
            MapData mapdata = new MapData();
            mapdata.mapurl = "MapViewer_GetMap.aspx?imagename=" + drawing.imagename.ToString();
            mapdata.areahtml = drawing.areamap.ToString();
            mapdata.scaletext = (1 / drawing.scale).ToString("0.00") + " " + MapUnits;

            if (!layermanager.Envelope.IsNull)
            {
                mapdata.top = layermanager.Envelope.STPointN(1).STY.ToString();
                mapdata.left = layermanager.Envelope.STPointN(1).STX.ToString();
                mapdata.bottom = layermanager.Envelope.STPointN(3).STY.ToString();
                mapdata.right = layermanager.Envelope.STPointN(3).STX.ToString();
            }

            // diagnostic - print the count of paths
            mapdata.pathcounter = drawing.pathcount.ToString();
            mapdata.geocounter = drawing.geocount.ToString();

            // diagnostic - stop counting time and list processing time in milliseconds
            stop = DateTime.Now;
            TimeSpan d = stop - start;
            mapdata.duration = d.ToString();

            // send back return data
            return mapdata;
        }
    }
}
